This tutorial follows from our introduction to multivariate linear models, extending it by using multivariate linear mixed models.
Useful packages:
library(MCMCglmm)
library(lme4)
library(brms)
library(tidyr)
library(dplyr)
library(corrplot)
library(broom.mixed)
library(dotwhisker)
library(ggplot2); theme_set(theme_bw())
Get data (previously downloaded from http://datadryad.org/bitstream/handle/10255/dryad.8377/dll.csv but ? now bit-rotted?)
dll_data <- read.csv("../data/dll.csv")
## make temp a factor (25 vs 30 degrees)
dll_data$temp <- factor(dll_data$temp)
## scale relevant variables (fancier but less repetition than previously)
morph_vars <- c("femur","tibia","tarsus","SCT")
morph_vars_sc <- paste(morph_vars,"s",sep="_")
dll_data2 <- dll_data
## c() drops unwanted structure from the results of scale()
for (i in 1:length(morph_vars)) {
dll_data2[[morph_vars_sc[i]]] <- c(scale(dll_data[[morph_vars[i]]]))
}
The previous expression for the multivariate model was
\[ \mathbf{Y} = \mathbf{XB} + \mathbf{E} \]
In contrast, the expression for the mixed model is
\[ y = \mathbf{X\beta} + \mathbf{Zb} + \epsilon \]
where \(\mathbf{b}\) is a set of Gaussian variables with a variance-covariance matrix \(\mathbf{\Sigma}\) which we estimate.
Suppose we have observations of \(m\) individuals, with \(p\) different observations (traits, or time points, or types of measurement, or …) for each individual. The way we’re going to make this work is to expand (“melt”, or gather() or pivot_longer() if we’re using tidyr) the data set to be \(mp\) observations long, then treat each individual (which was previously a single row of the data set but now comprises \(p\) rows) as a group (we’ll call this units):
lme4 does not (currently) have a natural syntax for multivariate responses, however, as I eluded to in class, there is an important relationship between multivariate response models and so called “repeated” measures (or longitudinal) models. As such we can use a few tricks to estimate the model in lme4. Below this, I will go through the same model using MCMCglmm, which is a library which has a more natural syntax for such multivariate responses, but is explicitly Bayesian, so you need to provide prior distributions.
What we need to first do (for lme4) is to generate a single column that represents the numeric values for our response traits, and then a second variable that stores the trait type.
dll_melt <- (dll_data2
%>% select(-c(femur,tibia,tarsus,SCT)) ## drop unscaled vars
%>% mutate(units=factor(1:n()))
%>% gather(trait,value, -c(units,replicate,line,genotype,temp))
%>% drop_na()
%>% arrange(units)
)
## saveRDS(dll_melt, file="dll_melt.rds")
(in case you’re familiar with current-day tidyverse: gather() is an earlier version of pivot_longer(), which is now recommended).
Look at how this has changed the structure of the data from a wide format:
head(dll_data) # original wide
## replicate line genotype temp femur tibia tarsus SCT
## 1 1 line-1 Dll 25 0.590 0.499 0.219 9
## 2 1 line-1 Dll 25 0.550 0.501 0.214 13
## 3 1 line-1 Dll 25 0.588 0.488 0.211 11
## 4 1 line-1 Dll 25 0.588 0.515 0.211 NA
## 5 1 line-1 Dll 25 0.596 0.502 0.207 12
## 6 1 line-1 Dll 25 0.577 0.499 0.207 14
to a long format:
head(dll_melt)
## replicate line genotype temp units trait value
## 1 1 line-1 Dll 25 1 femur_s 1.514
## 2 1 line-1 Dll 25 1 tibia_s 0.597
## 3 1 line-1 Dll 25 1 tarsus_s 1.751
## 4 1 line-1 Dll 25 1 SCT_s -1.222
## 5 1 line-1 Dll 25 2 femur_s 0.138
## 6 1 line-1 Dll 25 2 tibia_s 0.654
We can now go ahead and fit the model where we need to include trait as a predictor variable (where each trait is now a “repeated measure” from a particular subject/individual)
t1 <- system.time(
lmer1 <- lmer(value ~ trait:(genotype*temp) - 1 +
(trait-1|line) + (trait-1|units),
data=dll_melt,
control=lmerControl(
optimizer="bobyqa",
check.nobs.vs.nlev="ignore",
check.nobs.vs.nRE="ignore"))
)
system.time() business is just to keep track of how long the command takes to run (we could have kept the HTML output clean by hiding this in the .Rmd file, at the cost of making the .Rmd more complicated/confusing for those who were following along there)-1 to drop intercepttrait:(1+genotype+temp+genotype:temp)trait + trait:genotype + trait:temp + trait:genotype:temp(trait-1|line) means “variance/covariances of traits among lines”-1 so we consider traits, not differences among traits(trait-1|units) specifies “var/cov of traits among units (individuals)”lmer always includes a residual variance term. This is redundant because we have only one data point per individual per trait: lmerControl(...) tells lmer not complainoptimizer="bobyqa" is the only choice of optimizers that does not give a convergence warning (ask about this if you feel like going down a rabbit hole)print(lmer1), summary(lmer1) useful but awkward (16 fixed effect coefficients, we’ll look at graphical summaries insteadfixef() (fixed effects), ranef() (line/indiv deviations from pop mean), coef() (line/indiv-level estimates), VarCorr (random effects var/cov)getME(fit,"theta") extracts them if you need them for something.isSingular(lmer1)
## [1] FALSE
VarCorr(lmer1)
## Groups Name Std.Dev. Corr
## units traitfemur_s 0.654
## traitSCT_s 0.728 0.05
## traittarsus_s 0.565 0.58 0.20
## traittibia_s 0.670 0.91 0.12 0.47
## line traitfemur_s 0.489
## traitSCT_s 0.392 0.14
## traittarsus_s 0.462 0.81 0.37
## traittibia_s 0.473 0.87 0.22 0.83
## Residual 0.462
par(mfrow=c(1,2))
vv1 <- VarCorr(lmer1)
## fix unit variance-covariance by adding residual variance:
diag(vv1$units) <- diag(vv1$units)+sigma(lmer1)^2
corrplot.mixed(cov2cor(vv1$line),upper="ellipse")
corrplot.mixed(cov2cor(vv1$units),upper="ellipse")
Correlations of traits across lines are stronger than correlations within individuals. In both cases correlations are all positive (i.e. first axis of variation is size variation?)
cc1 <- tidy(lmer1,effect="fixed") %>%
tidyr::separate(term,into=c("trait","fixeff"),extra="merge",
remove=FALSE)
dwplot(cc1)+facet_wrap(~fixeff,scale="free",ncol=2)+
geom_vline(xintercept=0,lty=2)
These results tell approximately the same story (coefficients are consistent across traits within a fixed effect, e.g. effect of higher temperature is to reduce scores on all traits).
This is very slow, you probably don’t want to evaluate it on your computer
t1_CI <- system.time(cc2 <- tidy(lmer1,
effect = "ran_pars",
conf.int = TRUE,
conf.method = "profile",
parallel="multicore",
ncpus=8))
saveRDS(cc2, file="../data/cc2.rds")
(about 40 minutes to run on 8 cores on a fast machine)
Another option is the MCMCglmm package, which has a natural interface for general multivariate mixed models. It takes a while to get used to the interface, but here is an example. Please check out here for more information about the package, and here for an overview of how to use it.
First I find it easier (given the interface of MCMCglmm) to create a formula with the response variables and predictors. This is only for the fixed effects part of the model.
fmla.MMLM1 <- cbind(femur_s, tibia_s, tarsus_s, SCT_s) ~
trait:(genotype*temp) - 1
Now we need to let MCMCglmm know which family (i.e. distribution) the response variables are. Since all are normal (Gaussian), we can specify it the following way.
fam.test <- rep("gaussian", 4 )
Since MCMCglmm is fundamentally a Bayesian approach, it needs a prior. If you provide no prior by default, it tries a “flat” prior, although this rarely works. In this case we provide not-quite-flat priors only for the random effects of line and for the residual variances (could also provide them for the fixed effects). Choosing priors for variances and covariances is tricky (and too technical for right now), so we will use the default prior distributions (inverse-Wishart). Ian Dworkin has some simple tutorials where he draws out the effects of various common priors for variances and covariances.
prior.model.1 <- list( R = list(V=diag(4)/4, nu=0.004),
G = list(G1=list(V=diag(4)/4, nu=0.004)))
Let’s take a quick look at the prior
prior.model.1
## $R
## $R$V
## [,1] [,2] [,3] [,4]
## [1,] 0.25 0.00 0.00 0.00
## [2,] 0.00 0.25 0.00 0.00
## [3,] 0.00 0.00 0.25 0.00
## [4,] 0.00 0.00 0.00 0.25
##
## $R$nu
## [1] 0.004
##
##
## $G
## $G$G1
## $G$G1$V
## [,1] [,2] [,3] [,4]
## [1,] 0.25 0.00 0.00 0.00
## [2,] 0.00 0.25 0.00 0.00
## [3,] 0.00 0.00 0.25 0.00
## [4,] 0.00 0.00 0.00 0.25
##
## $G$G1$nu
## [1] 0.004
The R matrix prior is for the residuals. This is \(\mathbf{R}_{4,4}\) as we have 4 traits in the VCV matrix. We have have non-zero variances for each trait as the mode for the prior, and 0 for covariances. However this is a weak prior, so even small amounts of data will largely overcome the pull of the prior. Another sensible approach we have used is to make the prior proportional to the overall observed VCV, as there is a large literature on the proportionality of covariance matrices for morphology. This may not be sensible for other types of multivariate response measures.
##,depends.on=c("prior","mod_fm","get_data")}
t2 <- system.time(
MMLM1.fit <- MCMCglmm(fmla.MMLM1,
random=~ us(trait):line,
rcov=~ us(trait):units,
prior= prior.model.1,
data= dll_data2,
family = fam.test,
nitt= 10000, burnin= 2000, thin=10)
)
fmla.MMLM1 is the formula object we created abovelmer formulatrait term is a reserved word in MCMCglmm, letting it know we want to fit a multivariate mixed modelMCMCglmm automatically melts the data for us (and assigns the name trait the same way we did manually above)random=~us(trait):line asks MCMCglmm to fit an unstructured covariance matrix for the line term (i.e the different wild type genotypes we are examining).- “Unstructured” means we are estimating the complete 4 x 4 matrix of covariances (= 4*5/2 = 10 elements total)(trait-1|line) in lmer modelMCMCglmm also automatically adds a unitsrcov=~us(trait):units = (trait-1|units)MCMCglmm offers a few other options for variance-covariance structuresThe nitt is how many iterations for the MCMC we want to perform, and the burnin is how many should be ignored at the beginning of the random walk.
The fit takes 21 seconds.
Normally we would spend a fair bit of time on diagnostics of the MCMC, but for now we will just quickly check the trace plots and autocorrelation.
In the fitted object $Sol is for solution, which is the term used for fixed effects in MCMCglmm. $VCV is for the variance-covariance matrix.
library(lattice)
xyplot(MMLM1.fit$Sol[,1:4])
xyplot(MMLM1.fit$Sol[,13:16])
acf(MMLM1.fit$Sol[,1:2])
xyplot(MMLM1.fit$VCV[,1:4])
acf(MMLM1.fit$VCV[,1:3])
Nothing terribly worrying.
summary(MMLM1.fit)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Sample size = 800
##
## DIC: 17451
##
## G-structure: ~us(trait):line
##
## post.mean l-95% CI u-95% CI eff.samp
## traitfemur_s:traitfemur_s.line 0.2975 0.1251 0.491 710
## traittibia_s:traitfemur_s.line 0.2486 0.1073 0.418 674
## traittarsus_s:traitfemur_s.line 0.2282 0.0870 0.386 715
## traitSCT_s:traitfemur_s.line 0.0344 -0.0766 0.145 800
## traitfemur_s:traittibia_s.line 0.2486 0.1073 0.418 674
## traittibia_s:traittibia_s.line 0.2734 0.1302 0.437 713
## traittarsus_s:traittibia_s.line 0.2236 0.0959 0.381 707
## traitSCT_s:traittibia_s.line 0.0513 -0.0454 0.161 800
## traitfemur_s:traittarsus_s.line 0.2282 0.0870 0.386 715
## traittibia_s:traittarsus_s.line 0.2236 0.0959 0.381 707
## traittarsus_s:traittarsus_s.line 0.2648 0.1291 0.434 800
## traitSCT_s:traittarsus_s.line 0.0847 -0.0246 0.193 684
## traitfemur_s:traitSCT_s.line 0.0344 -0.0766 0.145 800
## traittibia_s:traitSCT_s.line 0.0513 -0.0454 0.161 800
## traittarsus_s:traitSCT_s.line 0.0847 -0.0246 0.193 684
## traitSCT_s:traitSCT_s.line 0.1912 0.0888 0.316 800
##
## R-structure: ~us(trait):units
##
## post.mean l-95% CI u-95% CI eff.samp
## traitfemur_s:traitfemur_s.units 0.6448 0.60342 0.6879 800
## traittibia_s:traitfemur_s.units 0.4019 0.36907 0.4403 800
## traittarsus_s:traitfemur_s.units 0.2143 0.18598 0.2421 800
## traitSCT_s:traitfemur_s.units 0.0253 -0.00434 0.0592 800
## traitfemur_s:traittibia_s.units 0.4019 0.36907 0.4403 800
## traittibia_s:traittibia_s.units 0.6648 0.62463 0.7110 800
## traittarsus_s:traittibia_s.units 0.1788 0.15157 0.2076 689
## traitSCT_s:traittibia_s.units 0.0601 0.02744 0.0922 579
## traitfemur_s:traittarsus_s.units 0.2143 0.18598 0.2421 800
## traittibia_s:traittarsus_s.units 0.1788 0.15157 0.2076 689
## traittarsus_s:traittarsus_s.units 0.5336 0.50056 0.5682 800
## traitSCT_s:traittarsus_s.units 0.0835 0.05463 0.1127 800
## traitfemur_s:traitSCT_s.units 0.0253 -0.00434 0.0592 800
## traittibia_s:traitSCT_s.units 0.0601 0.02744 0.0922 579
## traittarsus_s:traitSCT_s.units 0.0835 0.05463 0.1127 800
## traitSCT_s:traitSCT_s.units 0.7457 0.69455 0.7904 800
##
## Location effects: cbind(femur_s, tibia_s, tarsus_s, SCT_s) ~ trait:(genotype * temp) - 1
##
## post.mean l-95% CI u-95% CI eff.samp pMCMC
## traitfemur_s:genotypeDll 0.5035 0.3003 0.7225 800 <0.001 **
## traittibia_s:genotypeDll 0.6366 0.4431 0.8454 800 <0.001 **
## traittarsus_s:genotypeDll 0.6151 0.4125 0.8051 800 <0.001 **
## traitSCT_s:genotypeDll 0.6794 0.4929 0.8779 905 <0.001 **
## traitfemur_s:genotypewt 0.1754 -0.0321 0.3808 800 0.10
## traittibia_s:genotypewt 0.0186 -0.2018 0.2098 800 0.84
## traittarsus_s:genotypewt 0.4465 0.2357 0.6258 800 <0.001 **
## traitSCT_s:genotypewt -0.0796 -0.2388 0.1234 800 0.38
## traitfemur_s:temp30 -0.8352 -0.9570 -0.7330 835 <0.001 **
## traittibia_s:temp30 -0.8099 -0.9234 -0.6917 800 <0.001 **
## traittarsus_s:temp30 -1.2364 -1.3256 -1.1355 928 <0.001 **
## traitSCT_s:temp30 -0.8370 -0.9437 -0.7130 800 <0.001 **
## traitfemur_s:genotypewt:temp30 0.3628 0.2167 0.5022 800 <0.001 **
## traittibia_s:genotypewt:temp30 0.4740 0.3311 0.6339 800 <0.001 **
## traittarsus_s:genotypewt:temp30 0.5157 0.3881 0.6402 800 <0.001 **
## traitSCT_s:genotypewt:temp30 0.7248 0.5558 0.8695 800 <0.001 **
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Sometimes it is easier to look at the fixed and random effects separately.
summary(MMLM1.fit$Sol)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 800
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## traitfemur_s:genotypeDll 0.5035 0.1088 0.00385 0.00385
## traittibia_s:genotypeDll 0.6366 0.1045 0.00369 0.00369
## traittarsus_s:genotypeDll 0.6151 0.1038 0.00367 0.00367
## traitSCT_s:genotypeDll 0.6794 0.0979 0.00346 0.00325
## traitfemur_s:genotypewt 0.1754 0.1078 0.00381 0.00381
## traittibia_s:genotypewt 0.0186 0.1051 0.00372 0.00372
## traittarsus_s:genotypewt 0.4465 0.1018 0.00360 0.00360
## traitSCT_s:genotypewt -0.0796 0.0933 0.00330 0.00330
## traitfemur_s:temp30 -0.8352 0.0573 0.00203 0.00198
## traittibia_s:temp30 -0.8099 0.0585 0.00207 0.00207
## traittarsus_s:temp30 -1.2364 0.0495 0.00175 0.00162
## traitSCT_s:temp30 -0.8370 0.0595 0.00210 0.00210
## traitfemur_s:genotypewt:temp30 0.3628 0.0730 0.00258 0.00258
## traittibia_s:genotypewt:temp30 0.4740 0.0779 0.00275 0.00275
## traittarsus_s:genotypewt:temp30 0.5157 0.0659 0.00233 0.00233
## traitSCT_s:genotypewt:temp30 0.7248 0.0783 0.00277 0.00277
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## traitfemur_s:genotypeDll 0.2906 0.4268 0.5017 0.5799 0.714
## traittibia_s:genotypeDll 0.4248 0.5670 0.6401 0.7037 0.836
## traittarsus_s:genotypeDll 0.4122 0.5402 0.6151 0.6879 0.805
## traitSCT_s:genotypeDll 0.4881 0.6159 0.6807 0.7439 0.875
## traitfemur_s:genotypewt -0.0323 0.1005 0.1763 0.2515 0.379
## traittibia_s:genotypewt -0.1960 -0.0537 0.0224 0.0903 0.216
## traittarsus_s:genotypewt 0.2495 0.3794 0.4484 0.5155 0.642
## traitSCT_s:genotypewt -0.2541 -0.1428 -0.0829 -0.0210 0.115
## traitfemur_s:temp30 -0.9505 -0.8697 -0.8367 -0.7978 -0.721
## traittibia_s:temp30 -0.9311 -0.8467 -0.8099 -0.7718 -0.696
## traittarsus_s:temp30 -1.3328 -1.2696 -1.2357 -1.2029 -1.138
## traitSCT_s:temp30 -0.9592 -0.8760 -0.8386 -0.7973 -0.719
## traitfemur_s:genotypewt:temp30 0.2183 0.3168 0.3606 0.4104 0.507
## traittibia_s:genotypewt:temp30 0.3310 0.4219 0.4705 0.5273 0.633
## traittarsus_s:genotypewt:temp30 0.3919 0.4696 0.5154 0.5633 0.645
## traitSCT_s:genotypewt:temp30 0.5595 0.6765 0.7243 0.7751 0.872
And for the random effects.
summary(MMLM1.fit$VCV)
##
## Iterations = 2001:9991
## Thinning interval = 10
## Number of chains = 1
## Sample size per chain = 800
##
## 1. Empirical mean and standard deviation for each variable,
## plus standard error of the mean:
##
## Mean SD Naive SE Time-series SE
## traitfemur_s:traitfemur_s.line 0.2975 0.1092 0.003860 0.004097
## traittibia_s:traitfemur_s.line 0.2486 0.0971 0.003433 0.003741
## traittarsus_s:traitfemur_s.line 0.2282 0.0930 0.003289 0.003479
## traitSCT_s:traitfemur_s.line 0.0344 0.0575 0.002033 0.002033
## traitfemur_s:traittibia_s.line 0.2486 0.0971 0.003433 0.003741
## traittibia_s:traittibia_s.line 0.2734 0.0982 0.003471 0.003677
## traittarsus_s:traittibia_s.line 0.2236 0.0884 0.003127 0.003326
## traitSCT_s:traittibia_s.line 0.0513 0.0554 0.001960 0.001960
## traitfemur_s:traittarsus_s.line 0.2282 0.0930 0.003289 0.003479
## traittibia_s:traittarsus_s.line 0.2236 0.0884 0.003127 0.003326
## traittarsus_s:traittarsus_s.line 0.2648 0.0931 0.003292 0.003292
## traitSCT_s:traittarsus_s.line 0.0847 0.0577 0.002041 0.002207
## traitfemur_s:traitSCT_s.line 0.0344 0.0575 0.002033 0.002033
## traittibia_s:traitSCT_s.line 0.0513 0.0554 0.001960 0.001960
## traittarsus_s:traitSCT_s.line 0.0847 0.0577 0.002041 0.002207
## traitSCT_s:traitSCT_s.line 0.1912 0.0667 0.002357 0.002357
## traitfemur_s:traitfemur_s.units 0.6448 0.0214 0.000755 0.000755
## traittibia_s:traitfemur_s.units 0.4019 0.0182 0.000644 0.000644
## traittarsus_s:traitfemur_s.units 0.2143 0.0151 0.000534 0.000534
## traitSCT_s:traitfemur_s.units 0.0253 0.0162 0.000571 0.000571
## traitfemur_s:traittibia_s.units 0.4019 0.0182 0.000644 0.000644
## traittibia_s:traittibia_s.units 0.6648 0.0217 0.000765 0.000765
## traittarsus_s:traittibia_s.units 0.1788 0.0142 0.000503 0.000542
## traitSCT_s:traittibia_s.units 0.0601 0.0170 0.000601 0.000707
## traitfemur_s:traittarsus_s.units 0.2143 0.0151 0.000534 0.000534
## traittibia_s:traittarsus_s.units 0.1788 0.0142 0.000503 0.000542
## traittarsus_s:traittarsus_s.units 0.5336 0.0172 0.000608 0.000608
## traitSCT_s:traittarsus_s.units 0.0835 0.0150 0.000531 0.000531
## traitfemur_s:traitSCT_s.units 0.0253 0.0162 0.000571 0.000571
## traittibia_s:traitSCT_s.units 0.0601 0.0170 0.000601 0.000707
## traittarsus_s:traitSCT_s.units 0.0835 0.0150 0.000531 0.000531
## traitSCT_s:traitSCT_s.units 0.7457 0.0245 0.000865 0.000865
##
## 2. Quantiles for each variable:
##
## 2.5% 25% 50% 75% 97.5%
## traitfemur_s:traitfemur_s.line 0.16160 2.27e-01 0.2783 0.3471 0.5399
## traittibia_s:traitfemur_s.line 0.12914 1.85e-01 0.2313 0.2906 0.4650
## traittarsus_s:traitfemur_s.line 0.10862 1.70e-01 0.2144 0.2661 0.4260
## traitSCT_s:traitfemur_s.line -0.07225 -2.91e-05 0.0294 0.0681 0.1527
## traitfemur_s:traittibia_s.line 0.12914 1.85e-01 0.2313 0.2906 0.4650
## traittibia_s:traittibia_s.line 0.14471 2.09e-01 0.2538 0.3218 0.5119
## traittarsus_s:traittibia_s.line 0.10944 1.67e-01 0.2084 0.2607 0.4264
## traitSCT_s:traittibia_s.line -0.04298 1.42e-02 0.0464 0.0859 0.1664
## traitfemur_s:traittarsus_s.line 0.10862 1.70e-01 0.2144 0.2661 0.4260
## traittibia_s:traittarsus_s.line 0.10944 1.67e-01 0.2084 0.2607 0.4264
## traittarsus_s:traittarsus_s.line 0.13910 2.05e-01 0.2480 0.3095 0.4737
## traitSCT_s:traittarsus_s.line -0.00888 4.40e-02 0.0767 0.1175 0.2191
## traitfemur_s:traitSCT_s.line -0.07225 -2.91e-05 0.0294 0.0681 0.1527
## traittibia_s:traitSCT_s.line -0.04298 1.42e-02 0.0464 0.0859 0.1664
## traittarsus_s:traitSCT_s.line -0.00888 4.40e-02 0.0767 0.1175 0.2191
## traitSCT_s:traitSCT_s.line 0.10097 1.44e-01 0.1781 0.2237 0.3531
## traitfemur_s:traitfemur_s.units 0.60370 6.30e-01 0.6449 0.6585 0.6881
## traittibia_s:traitfemur_s.units 0.36872 3.89e-01 0.4020 0.4136 0.4399
## traittarsus_s:traitfemur_s.units 0.18654 2.04e-01 0.2142 0.2249 0.2440
## traitSCT_s:traitfemur_s.units -0.00714 1.47e-02 0.0254 0.0353 0.0570
## traitfemur_s:traittibia_s.units 0.36872 3.89e-01 0.4020 0.4136 0.4399
## traittibia_s:traittibia_s.units 0.62240 6.50e-01 0.6648 0.6778 0.7096
## traittarsus_s:traittibia_s.units 0.15131 1.70e-01 0.1780 0.1873 0.2074
## traitSCT_s:traittibia_s.units 0.02788 4.88e-02 0.0594 0.0718 0.0936
## traitfemur_s:traittarsus_s.units 0.18654 2.04e-01 0.2142 0.2249 0.2440
## traittibia_s:traittarsus_s.units 0.15131 1.70e-01 0.1780 0.1873 0.2074
## traittarsus_s:traittarsus_s.units 0.49860 5.22e-01 0.5331 0.5451 0.5673
## traitSCT_s:traittarsus_s.units 0.05471 7.30e-02 0.0837 0.0935 0.1127
## traitfemur_s:traitSCT_s.units -0.00714 1.47e-02 0.0254 0.0353 0.0570
## traittibia_s:traitSCT_s.units 0.02788 4.88e-02 0.0594 0.0718 0.0936
## traittarsus_s:traitSCT_s.units 0.05471 7.30e-02 0.0837 0.0935 0.1127
## traitSCT_s:traitSCT_s.units 0.69879 7.29e-01 0.7455 0.7615 0.7947
This is not the most friendly output, and it takes a while to get used to. However, we can see that we still have evidence for something interesting going, and we could extract the vectors of effects as we did above.
let’s look at the VCV matrix for the random effects of line in a slightly clearer way (as a matrix)
##' extract variance-covariance matrices for MCMCglmm objects
##' does not (yet) set cor, stddev, residual-var attributes
##' may be fragile: depends on group vars not having dots in them?
VarCorr.MCMCglmm <- function(object, ...) {
s <- summary(object$VCV)$statistics[,"Mean"]
grps <- gsub("^[^.]+\\.([[:alnum:]]+)$","\\1",names(s))
ss <- split(s,grps)
getVC <- function(x) {
nms <- gsub("^([^.]+)\\.[[:alnum:]]+$","\\1",names(x))
n <- length(nms)
L <- round(sqrt(n))
dimnms <- gsub("^([^:]+):.*$","\\1",nms[1:L])
return(matrix(x,dimnames=list(dimnms,dimnms),
nrow=L))
}
r <- setNames(lapply(ss,getVC),unique(grps))
return(r)
}
vv <- VarCorr(MMLM1.fit)
par(mfrow=c(1,2))
corrplot.mixed(cov2cor(vv$line),upper="ellipse")
corrplot.mixed(cov2cor(vv$units),upper="ellipse")
lme4 estimates (variables are in a different order)This is only a taste of what to do, and after this we could start asking questions about this genetic covariance matrix.
Compare fixed effects:
tt <- tidy(MMLM1.fit)
tt2 <- tidy(lmer1)
tt_comb <- bind_rows(lmer=tt,MCMCglmm=tt2,.id="model") %>%
filter(effect=="fixed")
dwplot(tt_comb)+geom_vline(xintercept=0,lty=2)
see vignette("brms_multivariate")
SLOW
library(brms)
t3 <- system.time(
brmsfit <- brm(
mvbind(femur_s, tibia_s, tarsus_s, SCT_s) ~ genotype*temp + (1|p|line) + (1|q|replicate),
data = dll_data2, chains = 4, cores = 4)
)
saveRDS(brmsfit,file="../data/multiv_brmsfit.rda")
This takes a long time! (\(\approx 40\) minutes, even computing the chains in parallel)
glmmTMB, brms …FIXME:
allFit not working?)